<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>组件注册及创建</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>

<body>
<fieldset>
    <legend>组件注册</legend>
    <div id="app1">
        <my-component1></my-component1>
    </div>
    <div id="app2">
        <my-component2></my-component2>
    </div>
    <div id="app3">
        <my-component3></my-component3>
    </div>
    <template id="t3">
        <p>我是通过template解耦，将定义在JavaScript中的HTML模板分离出来的组件</p>
    </template>
    <pre>
                Vue.component(&#x27;my-component2&#x27;, {
                    template: &#x27;&lt;div&gt;我是全局组件&lt;/div&gt;&#x27;
                })

                var app2 = new Vue({
                    el: &#x27;#app2&#x27;
                })

                var app3 = new Vue({
                    el: &#x27;#app3&#x27;,
                    components: {
                        &#x27;my-component3&#x27;: {
                            template: &#x27;&lt;div&gt;我是局部组件&lt;/div&gt;&#x27;
                        }
                    }
                })

                Vue.component(&#x27;my-component4&#x27;, {
                    template: &#x27;#t4&#x27;
                })

                var app4 = new Vue({
                    el: &#x27;#app4&#x27;
                })
        </pre>
    <div id="app4">
        <table>
            <tbody is='my-component4'></tbody>
        </table>
    </div>
    <template id="t4">
        <div>
            <p>我是特殊标签table内的组件</p>
            <pre>
                &lt;div id=&quot;app9&quot;&gt;
                &lt;table&gt;
                    &lt;my-component9&gt;...&lt;/my-component9&gt;
                &lt;/table&gt;
                &lt;/div
                以上方式不能正常渲染，在table内的自定义组件会被认为是无效的

                &lt;div id=&quot;app9&quot;&gt;
                &lt;table&gt;
                    &lt;tbody is=&#x27;my-component9&#x27;&gt;&lt;/tbody&gt;
                &lt;/table&gt;
                &lt;/div&gt;
                正确在table内使用自定义组件的方式，使用is属性来挂载组件
            </pre>
        </div>
    </template>
    <ul>
        <li>组件（Component）是Vue最强大的功能之一。组件可以扩展HTML元素，封装可重用的代码</li>
        <li>可以使用独立可复用的小组件来构建大型应用，任意类型的应用界面都可以抽象为一个组件树</li>
        <li>组件注册分为全局注册和局部注册</li>
        <li>调用Vue.component()是全局注册，在vue实例选项对象components属性内注册的组件是局部的</li>
        <li>全局组件所有的vue实例都可以调用，局部注册的组件只能在其对应的vue实例下使用</li>
        <li>组件中也可像Vue实例那样使用其他的选项，如data computed methods等。但data和实例使用稍有区别，组件中的data必须是函数，其值需return出来</li>
        <li>组件可以嵌套，组件中定义并使用其他组件，这就构成了父子组件的关系</li>
        <li>组件template标签下只能有一个根元素</li>
        <li>组件名称推荐使用小写字母加­进行命名（必须）, 如my­componnet方式命名组件</li>
        <li>组件在特殊html标签内使用受限，需要使用is属性来挂载组件（如table标签内只能是tr td 等表格相关元素不能使用自定义标签）</li>
        <li>组件优点：所有vue实例均可使用，一般实际开发过程中局部组件使用相对较多</li>
        <li>组件缺点：权限太大，容错率低</li>
    </ul>
</fieldset>

<fieldset>
    <legend>父子组件嵌套</legend>
    <div id="app5">
        <my-component5></my-component5>
    </div>
    <template id="t5">
        <div>
            <span>我是爷爷</span>
            <my-component6></my-component6>
        </div>
    </template>
    <template id="t6">
        <div>
            <span>我是爸爸</span>
            <my-component7></my-component7>
        </div>
    </template>
    <template id="t7">
        <div>
            <span>我是儿子</span>
        </div>
    </template>
</fieldset>

<fieldset>
    <legend>实例data和组件data</legend>
    <div id="app7">
        <div>
            <button @click="pull">{{numb}}</button>
            <button @click="pull">{{numb}}</button>
        </div>
        <div>
            <my-component77></my-component77>
            <my-component77></my-component77>
        </div>
    </div>
    <template id="t77">
        <button type="button" @click='number++'>{{number}}</button>
    </template>
    <pre>
                var data = {
                    number: 0
                }
                var app10 = new Vue({
                    el: &#x27;#app10&#x27;,
                    components: {
                        &#x27;my-component10&#x27;: {
                            template: &#x27;#t10&#x27;,
                            data: function () {
                                return data
                            }
                        }
                    }
                })
                var app11 = new Vue({
                    el: &#x27;#app11&#x27;,
                    components: {
                        &#x27;my-component11&#x27;: {
                            template: &#x27;#t11&#x27;,
                            data: function () {
                                return {
                                    number: 0
                                }
                            }
                        }
                    }
                })
        </pre>
    <p>1、由于JS中对象类型的变量实际上保存的是对象的引用，当多个组件时，会共享数据导致一个组件中数据的改变会引起其他组件数据的改变</p>
    <p>2、而子组件使用一个返回对象的函数，每次使用组件都会创建一个新的对象，这样就不会出现共享数据的问题</p>
</fieldset>

<script>
    Vue.component('my-component1', {
        template: '<p>我是全局组件</p>'
    });

    let app1 = new Vue({
        el: '#app1'
    });

    let app2 = new Vue({
        el: '#app2',
        components: {
            'my-component2': {
                template: '<p>我是局部组件</p>'
            }
        }
    });

    Vue.component('my-component3', {
        template: '#t3'
    });

    let app3 = new Vue({
        el: '#app3'
    });

    let app4 = new Vue({
        el: '#app4',
        components: {
            'my-component4': {
                template: '#t4'
            }
        }
    });
    /*组件注册*/


    let app5 = new Vue({
        el: '#app5',
        template: '#t5',
        components: {
            'my-component6': {
                template: '#t6',
                components: {
                    'my-component7': {
                        template: '#t7',
                    }
                }
            }
        }

    });
    /************************************************* 父子组件 ************************************************/

    let app7 = new Vue({
        el: '#app7',
        data: {
            numb: 0
        },
        methods: {
            pull: function () {
                this.numb++
            }
        },
        components: {
            'my-component77': {
                template: '#t77',
                data: function () {
                    return {
                        number: 0
                    }
                }
            }
        }
    })
</script>
</body>


</html>